﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace wontec_claw
{
    public partial class Form1 : Form
    {

        //串口相关
        SerialPort COM;
        int[] bpslist = { 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, 115200, 128000 ,256000,921600 };
        int[] canbps = {1000,800,666,500,400,250,200,125,100,80,50,40,20,10 };
        bool isOpen = false;
        List<byte> rxbuffer = new List<byte>(4096);
        int lastCount=0;
        int lastPos=0;
        List<byte[]> canSendCache = new List<byte[]>();
        //CAN
        public class CANINFO{
            public Action<byte[]> CAN_sendData;
            public Action<List<byte[]>> CAN_recvData;
            public Action<SerialPort> CAN_COM;
            public Action<List<byte>> CAN_COM_DataReceived;
            public Action<int> CAN_SetBps;
            public Action CAN_Close;
            public Form Window;

            public FieldInfo isOpenField;
            public bool isOpen
            {
                get { if (isOpenField != null) return (bool)isOpenField.GetValue(Window); return true; }
                set { if (isOpenField != null) isOpenField.SetValue(Window,value); }
            }
            public string Name;

        }
        Dictionary<string, CANINFO> CANList = new Dictionary<string, CANINFO>();
        CANINFO SelectCAN;
        List<byte[]> CAN_Data = new List<byte[]>();
        //设置
        Dictionary<Control, double> trsValue = new Dictionary<Control, double>();

        //
        Dictionary<string, string> fwurl = new Dictionary<string, string>();
        //指令翻译助手
        clawhelper CMD = new clawhelper();
        int SelectClawID=0;

        //更新参数相关
        bool needUpdate=false;
        bool beforSend = false;
        bool homestatscheck = false;
        bool blockset=true;
        bool ZcmdFlag = false;

        //设备ID列表
        List<int> clawnum = new List<int>();
        int needUpdatedrive=0;
        int lastSelectclaw = -1;
        List<int> cmdlist = new List<int>();
        List<int> cmdwrite = new List<int>();
        Dictionary<int,int> cmdreadtimeout = new Dictionary<int,int>();
        Dictionary<int, int> cmdwritetimeout = new Dictionary<int, int>();
        const int cmdmaxtimeout = 10;
        const int cmdmaxresend = 3;
        const int cmdblockCount = 2;//接受到$停止发送事件 避免冲突
        int cmdblocktimes;
        int getallver;

        //指令'I'回显次数
        int Iwiew = 0;
        //指令'i'回显
        int iwiew = 0;
        //选择设备跳过更新
        bool skipselect=false;

        //bool skipsaveconfig=true;

        //命令列表
        List<TextBox> savecmdlist = new List<TextBox>();

        enum HOME_MODE:int
        {
            HOME_ACT_POS=37,//设定原点
            HOME_SW_NEG_SPEED=27,//开关反向回零
            HOME_SW_POS_SPEED=23,//开关正向回零
            HOME_LIM_NEG_SPEED=18,//
            HOME_LIM_POS_SPEED=17,//
            HOME_THR_POS_SPEED=-3,//撞击正向回零
            HOME_THR_NEG_SPEED=-4,//撞击反向回零
        }

        //设备状态字符串字典
        Dictionary<int, string> statsstring = new Dictionary<int, string>();
        Dictionary<int, string> homestatsstring = new Dictionary<int, string>();
        List<int> homeid = new List<int>(new int[] { 23,27,-3 & 0xff, -4&0xff,37});

        //接受超时(100ms)
        int rxtimeout = 0;
        int maxtimeout = 3;
        Series rtma;
        Series rtpos;

        //滑块控制电机位置中间变量
        bool PosUserControl=false;

        //bootloader
        bool dlMode = false;
        List<byte> dlbuffer = new List<byte>(4096);
        YmodemGUI dl;
        sersonview dl2;

        //下载器模式
        bool bootloaderonly = false;

        //配置文件保存路径
        private string cfgpath;
         string configdata;
        //显示名称
        string ver = "v1.58";
#if false
        string softname = "森空步进调试器";
        string updatename = "skver.cfg";
        void InitView()  {
            tabControl1.SelectedIndexChanged -= tabControl1_SelectedIndexChanged;
            tabControl1.TabPages.RemoveAt(1);
            linkLabel1.Visible = linkLabel2.Visible = true;
        }
#else
        string softname = "Wontec步进调试器";
        string updatename = "ver.cfg";
        void InitView()  {}
#endif

        Action initAction;

        int can_framerset=0x10;
        void SendUartData(object str,bool updateinfo=true)
        {
            if(!CMD.CANMode)
            if (!COM.IsOpen) return;
            if (str is string)
            {
                datainfo.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "] 发送: " + str);
                if (updateinfo)
                    txinfo.Text = str as string;
                beforSend = true;
                COM.Write(str as string);
            }
            else if(str is byte[])
            {
                StringBuilder sb = new StringBuilder();
                var data = str as byte[];
                if (CMD.CANMode)
                {
                    sb.Append("[" + DateTime.Now.ToString("HH:mm:ss") + "] 发送: CAN[");
                    for (int i=0;i<4;i++)
                        sb.AppendFormat("{0:X2}", (data[-i+11]));
                    sb.Append($"][{can_framerset:X2}][ ");
                    for (int i = 0; i < 8; i++)
                        sb.AppendFormat("{0:X2} ", (data[i]));
                    sb.Append("]\r\n");
                    SelectCAN.CAN_sendData(data);
                }
                else {
                foreach (byte b in str as byte[])
                    sb.AppendFormat("{0:X2} ", b);
                sb.AppendLine();

                COM.Write(str as byte[], 0, (str as byte[]).Length);
                }
                datainfo.AppendText(sb.ToString());
                beforSend = true;
            }
            else if(str is byte[][])
            {
                canSendCache.AddRange(str as byte[][]);
            }
        }

        void SendUartDataNoLog(object str,bool beforSend = true)
        {
            if (!CMD.CANMode)
                if (!COM.IsOpen) return;

            if (str is string)
                COM.Write(str as string);
            else if (str is byte[])
            {
                if(CMD.CANMode)
                    SelectCAN.CAN_sendData(str as byte[]);
                else
                    COM.Write(str as byte[], 0, (str as byte[]).Length);
            }
        }

        void SendUartBytes(byte[] data)
        {
            if (!COM.IsOpen) return;
            COM.Write(data, 0, data.Length);
        }

        public Form1()
        {
            InitializeComponent();
            InitView();

            initAction = () => {
                updatelinkLabel1_LinkClicked(null, null);
            };

            //获取串口
            foreach (int i in bpslist)
            {
                bpsselect.Items.Add(i);
                //setbpscomboBox1.Items.Add(i)
            }
            bpsselect.SelectedIndex = 8;
            getcombutton13_Click(null, null);
            //getcombutton1_Click(null, null);
            setnumberbutton9.Enabled = false;

            foreach (int i in canbps)
            {
                canbpsselect.Items.Add(i+"K");
                //setbpscomboBox1.Items.Add(i)
            }
            canbpsselect.SelectedIndex = 0;


            //UART2CAN xcan = new UART2CAN();
            //var uartcan = new CANINFO();
            //uartcan.CAN_recvData = xcan.dataRecv;
            //uartcan.CAN_sendData = xcan.dataSend;
            //uartcan.CAN_SetBps = xcan.SetBPS;
            //uartcan.CAN_COM = xcan.setCOM;
            //uartcan.CAN_COM_DataReceived = xcan.COM_DataReceived;
            //CANList.Add("UART转CAN" as string, uartcan);

            SKCOM xcan = new SKCOM();
            var uartcan = new CANINFO();
            uartcan.CAN_recvData = xcan.dataRecv;
            uartcan.CAN_sendData = xcan.dataSend;
            uartcan.CAN_SetBps = xcan.SetBPS;
            uartcan.CAN_COM = xcan.setCOM;
            uartcan.CAN_COM_DataReceived = xcan.COM_DataReceived;
            CANList.Add("SK CAN" as string, uartcan);


            var info = new DirectoryInfo(Environment.CurrentDirectory);
            foreach(var f in info.GetFiles())
            {
                if(f.Name.ToUpper().IndexOf("CAN")==0&&(f.Extension==".exe"|| f.Extension == ".dll"))
                {
                    try
                    {
                        var ass = Assembly.LoadFile(f.FullName);
                        foreach (var t in ass.GetModules()[0].GetTypes())
                        {
                            var dataRecv = t.GetField("dataRecv");
                            if (dataRecv == null) break;
                            var dataSend = t.GetField("dataSend");
                            var setCOM = t.GetField("setCOM");
                            var recvcom= t.GetField("COM_DataReceived");
                            var setbps = t.GetField("SetBPS");
                            var close = t.GetField("Close");
                            var can =new CANINFO();
                            can.Window = t.GetConstructors()[0].Invoke(null) as Form;
                            can.CAN_recvData = (dataRecv.GetValue(can.Window) as Action<List<byte[]>>);
                            can.CAN_sendData = (dataSend.GetValue(can.Window) as Action<byte[]>);
                            can.CAN_SetBps = (setbps.GetValue(can.Window) as Action<int>);
                            if(close!=null)
                            can.CAN_Close= (close.GetValue(can.Window) as Action);
                            can.Window.Icon = Icon;
                            can.isOpenField = t.GetField("isOpen");
                            if (setCOM != null)
                            {
                                can.CAN_COM = (setCOM.GetValue(can.Window) as Action<SerialPort>);
                                can.CAN_COM_DataReceived = (recvcom.GetValue(can.Window) as Action<List<byte>>);
                            }
                            CANList.Add(f.Name, can);
                            break;
                        }
                    }
                    catch { }
                }
            }

            
            canselectcomboBox1.Items.AddRange(CANList.Keys.ToArray());
            canselectcomboBox1.SelectedIndex = 0;

            //串口初始化
            COM = new SerialPort();
            COM.BaudRate = (int)bpsselect.SelectedItem;
            COM.Parity = Parity.None;
            COM.DataBits = 8;
            COM.StopBits = StopBits.One;
            COM.DataReceived += COM_DataReceived;
            COM.ReadTimeout = 5;
            COM.ReadBufferSize = 51200;
            COM.ReadTimeout = 10;

            g1.Enabled = g2.Enabled = g3.Enabled = g4.Enabled= false;
            foreach (TabPage p in tabControl1.TabPages)
                savepage.Add(p);
            idinfocheck_CheckedChanged(null, null);

            trsValue.Add(motorhstrackBar1, 800);
            trsValue.Add(motorlstrackBar3, 800);
            motorhstrackBar1.Tag = motorhstextBox1;
            motorlstrackBar3.Tag = motorlstextBox3;
            motorhstextBox1.Tag = motorhstrackBar1;
            motorlstextBox3.Tag = motorlstrackBar3;
            detectmatrackBar1.Tag = detectmatextBox1;
            detectmatextBox1.Tag = detectmatrackBar1;

            detectmaxpossetbutton3.Tag = detectmaxpostextBox8;
            assemblybutton2.Tag = assemblytextBox1;
            detecthspossetbutton1.Tag = detecthspostextBox6;
            //
            linktracktext(speed2_trackBar2, speed2_textBox1);
            linktracktext(maxma2_track, maxma2_textBox);

            linktracktext(motormaxaccspeed2trackBar1, motormaxaccspeed2textBox1,8000);
            linktracktext(motorlsacctrackBar2, motorlsacctextBox2,8000);
            //

            

            //添加广播地址
            clawnum.Add(0);
            clawselectcomboBox1.Items.Add(string.Format("[{0:X2}] {1}", clawnum[0],"广播地址"));
            clawselectcomboBox1.SelectedIndex = 0;

            enableposcontrol_CheckedChanged(null, null);
            

            //string[] statsstring = new string[] { "夹持到目标", "夹持目标脱落", "没夹持到目标", "正在运行（夹持或放松）", "电爪放松完成（待机）" };
            //状态字符
            statsstring.Add(0, "运动中[0]");
            statsstring.Add(1, "到达[1]");
            statsstring.Add(2, "撞击 或 夹持成功[2]");
            statsstring.Add(3, "探测 或 安装成功[3]");
            statsstring.Add(4, "探测失败[4]");
            statsstring.Add(5, "松开到底[5]");
            statsstring.Add(6, "夹持到底[6]");
            statsstring.Add(7, "探测低速撞击[7]");
            statsstring.Add(8, "紧急停止[8]");
            statsstring.Add(9, "正在回零[9]");

            fwurl.Add("Cstep v", "https://gitee.com/Cccxs/cstep-open/raw/master/FW/");
            fwurl.Add("Cstep [A]", "https://gitee.com/Cccxs/cstep-open/raw/master/FW/");
            fwurl.Add("Cstep [B]", "https://gitee.com/Cccxs/cstep-open/raw/master/[B]FW/");

            homestatsstring.Add(0, "未回零");
            homestatsstring.Add(1, "回零成功");
            homestatsstring.Add(2, "回零失败");
            homestatsstring.Add(3, "回零失败 超过最大位置");
            homestatsstring.Add(9, "回零中...");

            //statsstring.Add(1, "夹持到目标");
            //statsstring.Add(4, "正在运行（夹持或放松）");
            //statsstring.Add(5, "电爪放松完成（待机）");
            //statsstring.Add(6, "没夹持到目标");
            //statsstring.Add(9, "正在回零");

            //初始化
            int[] rawdata = CMD[">01NFFFFBD980F2D3C1A9B3"];
            setsettinginfo(rawdata,2);
            poscontroltrackBar3.Maximum = 30000;
            poscontroltrackBar3.Minimum = -rawdata[8] - 1000;
            setmotorinfo(CMD[">01R000186A0000F424032001002710000001040CF2B"]);
            setdetectinfo(CMD[">01F00004E2000004E2000030D40000003E8000950"]);
            sethomeinfo(CMD[">01BFD00009C4000009C40000007D032100000BB8000F42408C6F"]);
            setwinfo(CMD[">01W010100100000209C40000007D03C8ED9\r\n"]);

            speed2_trackBar2.Value = speed_trackBar2.Value;
            maxma2_track.Value = maxma_track.Value;

            for (int i = 0; i < 6; i++)
            {
                progselectcomboBox1.Items.Add("程序" + i);
            }
            

            

            //定时检测串口是否意外关闭
            Timer comcheck = new Timer();
            comcheck.Interval = 1000;
            comcheck.Tick += (object sender, EventArgs e) => {
                if (initAction != null)
                {
                    var act = initAction;
                    initAction = null;
                    act();
                }
                if (isOpen == true)
                {
                    if (CMD.CANMode)
                    {

                        if (SelectCAN.CAN_COM != null)
                        {
                            if (COM.IsOpen == false)
                                opencom_Click(null, null);
                        }
                        else if (!SelectCAN.isOpen)
                            opencom_Click(null, null);
                    }
                    else if (COM.IsOpen == false)
                    {
                        if (dlMode)
                        {
                            if (++errorcount == 3)
                                opencom_Click(null, null);
                        }
                        else
                            opencom_Click(null, null);
                        //如果在下载过程中中断
                        //if (dlMode)
                        //    dl.Error = true;
                    }
                    else errorcount = 0;
                    //g1.Enabled = g2.Enabled = g3.Enabled = g4.Enabled = false;
                    //comselect.Enabled = true;
                    //bpsselect.Enabled = true;
                    //getcombutton13.Enabled = true;
                    //opencom.Text = "打开串口";

                    
                    
                }

                //自动获取站号
                if (isOpen)
                {
                    if (autogetid_check.Checked)
                    {
                        //CMD_DR_Click(null, null);
                        SendUartDataNoLog(CMD['$']);
                    }
                    else if (homestatscheck)
                    {
                        SendUartDataNoLog(CMD['g',SelectClawID]);
                    }
                }
            };
            comcheck.Start();

            //电流图表

            rtma = new Series("mA");
            rtma.ChartType = SeriesChartType.Line;
            rtma.Color = Color.Red;
            //rtma.BorderWidth = 2;
            //rtma.ShadowOffset = 2;
            //rtma.MarkerStyle = MarkerStyle.Diamond;
            rtma.IsVisibleInLegend = false;
            //rtma.IsValueShownAsLabel = false;

            rtpos = new Series("Pos");
            rtpos.ChartType = SeriesChartType.Line;
            //rtpos.BorderWidth = 2;
            //rtpos.ShadowOffset = 2;
            //rtpos.MarkerStyle = MarkerStyle.Diamond;
            rtpos.IsVisibleInLegend = false;
            //rtpos.IsValueShownAsLabel = false;
            rtpos.YAxisType = AxisType.Secondary;


            realtimema.Series.Clear();
            realtimema.Series.Add(rtma);
            realtimema.Series.Add(rtpos);
            realtimema.ChartAreas[0].AxisY.Maximum = maxma_track.Value+5;
            realtimema.ChartAreas[0].AxisY2.Enabled = AxisEnabled.True;
            realtimema.ChartAreas[0].AxisX.IsLabelAutoFit = false;
            realtimema.ChartAreas[0].AxisY2.LabelAutoFitStyle = LabelAutoFitStyles.DecreaseFont;

            realtimema.ChartAreas[0].AxisY2.Maximum = poscontroltrackBar3.Maximum;
            realtimema.ChartAreas[0].AxisY2.Minimum = poscontroltrackBar3.Minimum;


            //串口命令列表
            for(int i = 0; i < MAXUSERUARTCMD; i++)
            {
                var b = new Button();
                b.Location = new Point(txb1.Location.X, txb1.Location.Y+i*25);
                b.Size = txb1.Size;
                b.Text = "" + (i + 1);

                var t = new TextBox();
                t.Location = new Point(txt1.Location.X, txt1.Location.Y + i * 25);
                t.Size = txt1.Size;

                b.Tag = t;
                t.Tag = b;

                b.Click += (object s, EventArgs e) =>
                  {
                      var str = ((TextBox)((Control)s).Tag).Text;
                      if (str.Length != 0)
                      {
                          txinfo.Text = string.Format(str,SelectClawID);
                          txlastdataButton_Click(null, null);
                      }
                  };

                savecmdlist.Add(t);

                panel1.Controls.Add(t);
                panel1.Controls.Add(b);
            }

            cfgpath = Environment.CurrentDirectory+"\\" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ".cfg";
            if(!File.Exists(cfgpath))
                cfgpath = System.IO.Path.GetTempPath() + System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ".cfg";


            datainfo.MouseWheel += (object sender, MouseEventArgs e) =>
            {
                if (e.Delta > 0)
                {
                    datainfo.Focus();
                    datainfo.Location = new Point(datainfo.Location.X,542-(500-89-89));
                    datainfo.Size = new Size(datainfo.Size.Width, 500-89);
                }
                else
                {
                    //datainfo.Location = new Point(datainfo.Location.X, 542 );
                    //datainfo.Size = new Size(datainfo.Size.Width, 49);
                }
            };

            datainfo.LostFocus += (object sender, EventArgs e) =>
            {
                datainfo.Size = new Size(datainfo.Size.Width, 89);
                datainfo.Location = new Point(datainfo.Location.X, 542);
            };

            datainfo.KeyPress
                += (object sender, KeyPressEventArgs e) =>
            {
                if (e.KeyChar == (char)Keys.Escape)
                {
                    datainfo.Size = new Size(datainfo.Size.Width, 89);
                    datainfo.Location = new Point(datainfo.Location.X, 542);
                }
            };

            //循环判断解析串口数据
            Timer comrecv = new Timer();
            comrecv.Interval = 1;
            comrecv.Tick += (object sender, EventArgs e) => {

                if (CMD.CANMode)
                {
                    if (SelectCAN.CAN_COM_DataReceived != null)
                        SelectCAN.CAN_COM_DataReceived(CMD.canBuffer);
                    if (canSendCache.Count != 0)
                    {
                        //SelectCAN.CAN_sendData(canSendCache[0]);
                        SendUartData(canSendCache[0]);
                        canSendCache.RemoveAt(0);
                    }
                    //var candata=CMD.candecode();
                    if (CAN_Data.Count != 0)
                    {
                        var candata = CMD[CAN_Data[0]];
                        var dat = CAN_Data[0];
                        CMD.canid = dat[8] | (dat[9] << 8) | (dat[10] << 16) | (dat[11] << 24);
                        for (int i = 0; i < 8; i++)
                            CMD.candata[i] = dat[i];
                        CAN_Data.RemoveAt(0);
                        if (dat.Length > 12) can_framerset = dat[12];
                        if (candata != null)
                            recvcandata(candata);
                    }
                    return;
                }

                if (lastCount != rxbuffer.Count)
                {
                    if (rxbuffer.Count == 0) return;
                    while (rxbuffer.Count != 0)
                    {
                        if (rxbuffer[0] != '>')
                        {
                            if (rxbuffer[0] > 126)
                            {
                                if(datainfobigchar[0]==0)
                                    datainfobigchar[0] = rxbuffer[0];
                                else
                                {
                                    datainfobigchar[1] = rxbuffer[0];
                                    datainfocache.Append(Encoding.Default.GetString(datainfobigchar));
                                    datainfobigchar[0] = 0;
                                }
                            }
                            else
                            {
                                if (datainfobigchar[0]!=0)
                                {
                                    datainfocache.Append((char)datainfobigchar[0]);
                                    datainfobigchar[0] = 0;
                                }
                                datainfocache.Append((char)rxbuffer[0]);
                            }
                            rxbuffer.RemoveAt(0);
                            continue;
                        }
                        break;
                    }
                    lastCount = rxbuffer.Count;
                    int i;
                    for (i = lastPos; i < lastCount; i++)
                    {
                        if (rxbuffer[i] == '\n')
                        {
                            byte[] b = new byte[i + 1];
                            for (int j = 0; j < i + 1; j++)
                            {
                                b[j] = rxbuffer[0];
                                rxbuffer.RemoveAt(0);
                            }
                            lastCount = 0;
                            lastPos = 0;
                            string recvcmd = Encoding.Default.GetString(b, 0, b.Length);
                            recvdata(CMD[recvcmd],recvcmd);
                            return;
                        }
                    }
                    lastPos = i;
                }
            };
            comrecv.Start();

            posmax = poscontroltrackBar3.Maximum;
            posmin = poscontroltrackBar3.Minimum;

            //定时获取位置信息
            Timer infoauto = new Timer();
            infoauto.Interval = 150;
            infoauto.Tick += (object sender, EventArgs e) =>
            {
                
                if (datainfocache.Length != 0)
                {
                    datainfo.AppendText(datainfocache.ToString());
                    datainfocache.Clear();
                }
                if (chartupdatesize>0)
                {
                    --chartupdatesize;
                }
                else
                {
                    
                    if (poscontroltrackBar3.Maximum != posmax)
                    {
                        realtimema.ChartAreas[0].AxisY2.Maximum = poscontroltrackBar3.Maximum = posmax;
                        chartupdatesize = 4;
                    }
                    if (poscontroltrackBar3.Minimum != posmin)
                    {
                        realtimema.ChartAreas[0].AxisY2.Minimum = poscontroltrackBar3.Minimum = posmin;
                        chartupdatesize = 4;
                    }
                }

                if (!isOpen) return;
                if (dlMode) return;

                if (getallver > 1)
                {
                    SendUartData(CMD['A', clawnum[clawnum.Count-(getallver - 1)]]);
                    getallver--;
                    if (getallver == 1) getallver = 0;
                }
                else if (cmdlist.Count != 0)
                {
                    if (cmdblocktimes != 0)
                    {
                        cmdblocktimes--;
                        if (cmdblocktimes == 0)
                            if (infoautogetcheckBox1.Checked)
                                getallver = clawnum.Count;
                        return;
                    }
                    if (false == cmdreadtimeout.ContainsKey(cmdlist[0]))
                        cmdreadtimeout.Add(cmdlist[0], cmdmaxtimeout + cmdmaxresend * 256);
                    else
                        cmdreadtimeout[cmdlist[0]] += cmdmaxtimeout;
                    SendUartData(CMD[(char)cmdlist[0], SelectClawID]);
                    cmdlist.RemoveAt(0);
                    return;
                }
                else if (cmdreadtimeout.Keys.Count != 0)
                {
                    var key = cmdreadtimeout.Keys.ToArray();
                    foreach (int k in key)
                    {
                        if ((cmdreadtimeout[k] & 0xff) != 0)
                            if (((--cmdreadtimeout[k]) & 0xff) == 0)
                            {
                                if (((cmdreadtimeout[k] >> 8) & 0xff) != 0)
                                {
                                    cmdreadtimeout[k] -= 256;
                                    cmdlist.Add(k);
                                }
                                else
                                {
                                    cmdreadtimeout.Remove(k);
                                }
                                return;
                            }
                    }
                }
                else if (blockset)
                {
                    blockset = false; return;
                }
                if (cmdwrite.Count != 0)
                {
                    if (false == cmdwritetimeout.ContainsKey(cmdwrite[0]))
                        cmdwritetimeout.Add(cmdwrite[0], cmdmaxtimeout + cmdmaxresend * 256);
                    else
                        cmdwritetimeout[cmdwrite[0]] += cmdmaxtimeout;
                    writeCMD();
                    return;
                }
                else if (cmdwritetimeout.Keys.Count != 0)
                {
                    //int len = cmdwritetimeout.Keys.Count;
                    var key = cmdwritetimeout.Keys.ToArray();
                    foreach (int k in key)
                    {
                        if ((cmdwritetimeout[k] & 0xff) != 0)
                            if (((--cmdwritetimeout[k]) & 0xff) == 0)
                            {
                                if (((cmdwritetimeout[k] >> 8) & 0xff) != 0)
                                {
                                    cmdwritetimeout[k] -= 256;
                                    cmdwrite.Add(k);
                                }
                                else
                                {
                                    cmdwritetimeout.Remove(k);
                                }
                                return;
                            }
                    }
                }
                if (beforSend)
                {
                    beforSend = false;
                    return;
                }
                if (autosettingcheckBox4.Checked)
                {
                    if (needUpdate)
                    {
                        needUpdate = false;
                        updatedatabutton2_Click(null, null);
                        return;
                    }
                    //infobutton1_Click(null, null);
                }
                
                if (needUpdatedrive != 0)
                {
                    SendUartData(CMD['$']);
                    needUpdatedrive--;
                    if (needUpdatedrive == 0)
                        lastSelectclaw = -1;
                    return;
                }

                //定时查询状态(最低优先级
                if (!stopchartcheckBox1.Checked)
                    if (SelectClawID != 0)
                        SendUartDataNoLog(CMD['I', SelectClawID], false);

                if (++rxtimeout == maxtimeout)
                {
                    if (rxbuffer.Count != 0)
                        datainfocache.Append(Encoding.Default.GetString(rxbuffer.ToArray()));
                    lastCount = lastPos = 0;
                    rxbuffer.Clear();
                }
            };
            infoauto.Start();

            if (bootloaderonly)
            {
                Text = "Cstep下载器";
                groupBox1.Location = new Point(12, 12);
                Size = new Size(295+36,144+48);
                g1.Visible = false;
                g2.Visible = false;
                g3.Visible = false;
                canselectcomboBox1.Visible = opencancom.Visible = false;
                infoautogetcheckBox1.Checked = false;
                groupBox2.Visible = false;
                statslabel10.Visible = false;
                label9.Visible = false;
                MaximizeBox = false;
                MinimizeBox = false;
                FormBorderStyle = FormBorderStyle.FixedSingle;
                if (dl == null)
                {
                    dl = new YmodemGUI(SendUartBytes, dlbuffer);
                    dl.beforCMD = "[iap=1]\r\n";
                    Icon = dl.Icon;
                }
            }
        }

        void recvcandata(int[] data)
        {
            recvdata(data, string.Format("CAN[{0:X8}][{9:X2}][ {1:X2} {2:X2} {3:X2} {4:X2} {5:X2} {6:X2} {7:X2} {8:X2} ]\r\n", CMD.canid,CMD.candata[0], CMD.candata[1], CMD.candata[2], CMD.candata[3], CMD.candata[4], CMD.candata[5], CMD.candata[6], CMD.candata[7], can_framerset));
        }

        void recvdata(int[] data,string recvcmd, bool enablelog=true)
        {
            if (data != null&&data.Length!=0)
            {
                switch (data[1])
                {
                    case 'I':
                        if (Iwiew == 0) enablelog = false;
                        else Iwiew--;
                        break;
                    case '$':
                        if (autogetid_check.Checked)
                        {
                            if (iwiew != 0)
                                iwiew = 0;
                            else
                                enablelog = false;
                        }
                        break;
                }

                if (SelectClawID == data[0] || data[1] == '$' || data[1] == 'i' || data[1] == 'A')
                    switch (data[1])
                    {
                        case 'A':
                            try
                            {

                            skipselect = true;
                                //if (data.Length == 3)
                                if (CMD.CANMode)
                                {
                                    StringBuilder sb = new StringBuilder();
                                    for (int i = 0; i < 8; i++)
                                        sb.Append((char)data[2 + i]);
                                    clawselectcomboBox1.Items[clawnum.IndexOf(data[0])] = string.Format("[{0:X2}] {0}{1} {2}", data[0], "号设备", sb.ToString());
                                }

                                else
                                    clawselectcomboBox1.Items[clawnum.IndexOf(data[0])] = string.Format("[{0:X2}] {0}{1} {2}", data[0], "号设备", recvcmd.Substring(4, data[2]));
                            //else {
                            //    string s = "";
                            //    for (int i = 0; i < 8; i++)
                            //        s += (char)data[2+i];
                            //    clawselectcomboBox1.Items[clawnum.IndexOf(data[0])] = string.Format("[{0:X2}] {0}{1} {2}", data[0], "号设备",s);
                            //}
                            }
                            catch { }
                            break;
                        case 'B':
                            sethomeinfo(data);
                            break;
                        case 'P':
                            setpidinfo(data);
                            break;
                        case 'N':
                            setsettinginfo(data, 2);
                            break;
                        case 'W':
                            setwinfo(data);
                            break;
                        case 'R':
                            setmotorinfo(data);
                            break;
                        case 'F':
                            setdetectinfo(data);
                            break;
                        case 'i':
                            if (!clawnum.Contains(data[0]))
                            {
                                clawnum.Add(data[0]);
                                clawselectcomboBox1.Items.Add(string.Format("[{0:X2}] {0}{1}", data[0], "号设备"));
                            }
                            int oldselect = clawselectcomboBox1.SelectedIndex;
                            skipselect = oldselect == clawnum.IndexOf(data[0]);
                            clawselectcomboBox1.SelectedIndex = clawnum.IndexOf(data[0]);
                            if (oldselect != clawselectcomboBox1.SelectedIndex)
                            {
                                clawselectcomboBox1.Items.RemoveAt(oldselect);
                                clawnum.RemoveAt(oldselect);
                            }
                            break;
                        case 'I':
                            //if (6 != formatRead(str.ToUpper(), ">%2x%c%8x%2x%1x%1x", data))
                            //poscontroltrackBar3.Value = data[2];
                            poscontorltextBox6.Text = "" + data[2];
                            if (poscontroltrackBar3.Maximum < data[2])
                            {
                                posmax = data[2] + 10000;
                            }
                            if (poscontroltrackBar3.Minimum > data[2])
                            {
                                posmin = data[2] - 10000;
                            }
                            var value = data[2];
                            if (value > poscontroltrackBar3.Maximum)
                                value = poscontroltrackBar3.Maximum;
                            if (value < poscontroltrackBar3.Minimum)
                                value = poscontroltrackBar3.Minimum;

                            if (!PosUserControl)
                                poscontroltrackBar3.Value = value;

                            rtma.Points.AddY(data[3]);
                            rtpos.Points.AddY(data[2]);
                            rtmavaluelabel10.Text = "" + data[3];
                            if (rtma.Points.Count > 100)
                            {
                                rtma.Points.RemoveAt(0);
                                rtpos.Points.RemoveAt(0);
                            }
                            if (data[4] == 0)
                            {
                                enablemotor_b.BackColor = this.BackColor;
                                disablemotor_b.BackColor = Color.Red;
                            }
                            else
                            {
                                enablemotor_b.BackColor = Color.LawnGreen;
                                disablemotor_b.BackColor = this.BackColor;
                            }

                            if (statsstring.ContainsKey(data[5]))
                                statslabel10.Text = statsstring[data[5]];
                            else
                                statslabel10.Text = "未知状态 " + data[5];
                            if (data[5] != 9)
                            {
                                homestatscheck = false;
                                homebutton6.Text = "回零";
                            }
                            //if (data[5] == 0)
                            //{
                            //    enabeclawbutton4.ForeColor = this.ForeColor;
                            //    disableclawbutton5.ForeColor = Color.Green;
                            //}
                            //else
                            //{
                            //    enabeclawbutton4.ForeColor = Color.Green;
                            //    disableclawbutton5.ForeColor = this.ForeColor;
                            //}
                            break;
                        case 'g':
                            //if (3 != formatRead(str.ToUpper(), ">%2x%c%2x", data))
                            if (homestatsstring.ContainsKey(data[2]))
                            {
                                homebutton6.Text = homestatsstring[data[2]];
                            }
                            else
                            {

                            }
                            break;
                        case 'Z':
                            //if (3 != formatRead(str.ToUpper(), ">%2x%c%2x", data))
                            if (data[2] == 0)
                            {
                                if (ZcmdFlag)
                                {
                                    ZcmdFlag = false;
                                    MessageBox.Show("校准成功", "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                                }
                            }
                            else
                            {
                                if (ZcmdFlag)
                                {
                                    ZcmdFlag = false;
                                    MessageBox.Show("校准失败", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                }
                            }
                            break;
                        case '$':
                            if (!clawnum.Contains(data[2]))
                            {
                                clawnum.Add(data[2]);
                                clawselectcomboBox1.Items.Add(string.Format("[{0:X2}] {0}{1}", data[2], "号设备"));
                                if (lastSelectclaw != -1)
                                {
                                    if (lastSelectclaw == data[2])
                                    {
                                        clawselectcomboBox1.SelectedIndex = clawselectcomboBox1.Items.Count - 1;
                                        lastSelectclaw = -1;
                                    }
                                }
                                if (clawnum.Count == 2)
                                    clawselectcomboBox1.SelectedIndex = 1;
                                cmdblocktimes = cmdblockCount;
                            }
                            break;
                        case 'd':
                            if (statsstring.ContainsKey(data[2]))
                                statslabel10.Text = statsstring[data[2]];
                            else
                                statslabel10.Text = "未知状态 " + data[2];
                            break;
                    }
                if (cmdreadtimeout.ContainsKey(data[1]))
                    cmdreadtimeout.Remove(data[1]);

                if (cmdwritetimeout.ContainsKey(data[1]))
                    cmdwritetimeout.Remove(data[1]);
            }
            if (enablelog)
                datainfo.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "] 接收: " + recvcmd);
            
        }

        private void CANComReceived(object sender, SerialDataReceivedEventArgs e)
        {
            throw new NotImplementedException();
        }

        private void getPortDeviceName(ComboBox cb)
        {
            using (System.Management.ManagementObjectSearcher searcher = new System.Management.ManagementObjectSearcher
            ("select * from Win32_PnPEntity where Name like '%(COM%'"))
            {
                var hardInfos = searcher.Get();
                foreach (var hardInfo in hardInfos)
                {
                    if (hardInfo.Properties["Name"].Value != null)
                    {
                        string deviceName = hardInfo.Properties["Name"].Value.ToString();
                        cb.Items.Add(deviceName);
                    }
                }
            }
        }

        //byte[] tempbyte =new byte[4096];
        private void COM_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            rxtimeout = 0;
            byte[] temp = new byte[COM.BytesToRead];
            COM.Read(temp, 0, temp.Length);
            try { 
            if (dlMode)
                dlbuffer.AddRange(temp);
            else if (CMD.CANMode)
                CMD.canBuffer.AddRange(temp);
            else
                rxbuffer.AddRange(temp);
            }
            catch { }
        }


        void loadconfig()
        {
            
            System.IO.StreamReader sr = new System.IO.StreamReader(cfgpath);
            try
            {
                List<string> ls = new List<string>();
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < MAXUSERUARTCMD+7; i++)
                {
                    string v = sr.ReadLine();
                    ls.Add(v);
                    sb.AppendLine(v);
                }
                sr.Close();
                configdata = sb.ToString();
                Invoke(new MethodInvoker(() =>
                {
                    for (int i = 0; i < savecmdlist.Count; i++)
                    {
                        savecmdlist[i].Text = ls[7 + i];
                    }
                    g4.Visible = ls[0] == "False";
                    infoautogetcheckBox1.Checked = ls[2] == "True";
                    idinfocheck.Checked = ls[3] == "True";
                    autogetid_check.Checked = ls[4] == "True";
                    warrinfocheckBox3.Checked = ls[5] == "True";
                    exttoolsbutton12_Click(null, null);
                    saveinfocheck.Checked = ls[1] == "True";
                    CRC16ENcheckBox1.Checked = ls[6] == "True";
                }));
                
                //sr.ReadLine()
            }
            catch { }
        }

        void saveconfig()
        {
            StringBuilder sw = new StringBuilder();
            sw.AppendLine(g4.Visible ? "True" : "False");
            sw.AppendLine(saveinfocheck.Checked?"True":"False");
            sw.AppendLine(infoautogetcheckBox1.Checked ? "True" : "False");
            sw.AppendLine(idinfocheck.Checked ? "True" : "False");
            sw.AppendLine(autogetid_check.Checked ? "True" : "False");
            sw.AppendLine(warrinfocheckBox3.Checked ? "True" : "False");
            sw.AppendLine(CRC16ENcheckBox1.Checked ? "True" : "False");
            for (int i = 0; i < savecmdlist.Count; i++)
                sw.AppendLine(savecmdlist[i].Text);
            //sw.AppendLine();
            string config = sw.ToString();
            if (config != configdata)
            {
                System.IO.FileStream fs = new System.IO.FileStream(cfgpath, System.IO.FileMode.OpenOrCreate);
                var code=Encoding.Default.GetBytes(config);
                fs.Write(code, 0, code.Length);
                fs.Flush();
                fs.Close();
            }
        }
        protected override void OnClosing(CancelEventArgs e)
        {
            if (saveinfocheck.Checked)
            {
                saveconfig();
            }
            base.OnClosing(e);
        }

        void clawclear(int sendcount = 2)
        {
            if (clawnum.Count > 1)
            {
                lastSelectclaw = sendcount!=0?SelectClawID:-1;
                clawselectcomboBox1.SelectedIndex = 0;
                int i = clawnum.Count - 1;
                while(i--!=0)
                {
                    clawselectcomboBox1.Items.RemoveAt(1);
                    clawnum.RemoveAt(1);
                }
                needUpdatedrive = sendcount;
            }
        }

        private void opencom_Click(object sender, EventArgs e)
        {
            if (isOpen)
            {
                if(COM.IsOpen)
                    COM.Close();
                isOpen = false;
                g1.Enabled = g2.Enabled = g3.Enabled = g4.Enabled = false;
                comselect.Enabled = true;
                bpsselect.Enabled = true;
                getcombutton13.Enabled = true;
                opencom.Text = "打开RS485";
                opencancom.Text = "打开CAN";
                commodelabel3.Text = "";
                if (CMD.CANMode)
                    if (SelectCAN.CAN_Close != null)
                        SelectCAN.CAN_Close();
            }
            else
            {
                CMD.CANMode = sender != opencom;
                if (CMD.CANMode)
                {
                    CAN_Data.Clear();
                    SelectCAN = CANList[canselectcomboBox1.SelectedItem as string];
                    SelectCAN.CAN_recvData(CAN_Data);
                    if (SelectCAN.Window != null)
                    {
                        if (SelectCAN.CAN_SetBps != null) SelectCAN.CAN_SetBps(canbps[canbpsselect.SelectedIndex]);
                        if (SelectCAN.Window.ShowDialog() != DialogResult.OK) return;
                    }
                    if (SelectCAN.CAN_COM != null)
                    {
                        SelectCAN.CAN_COM(COM);
                    }
                    else
                        isOpen = true;
                }
                if (!isOpen)
                {
                    if (comselect.Items.Count == 0)
                    {
                        MessageBox.Show("无可用端口");
                        return;
                    }
                    try
                    {
                        int start = comselect.Text.IndexOf("(COM") + 1;
                        int end = 0;
                        foreach (char c in comselect.Text.Substring(start + 3))
                        {
                            if (c > '9' || c < '0') break;
                            end++;
                        }
                        COM.PortName = comselect.Text.Substring(start, end + 3);
                        COM.BaudRate = bpslist[bpsselect.SelectedIndex];
                        COM.Open();
                        isOpen = true;

                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("打开串口失败\r\n" + ex.Message);
                        return;
                    }
                }
                if (isOpen)
                {
                    g1.Enabled = g2.Enabled = g3.Enabled = g4.Enabled = true;
                    comselect.Enabled = false;
                    bpsselect.Enabled = false;
                    getcombutton13.Enabled = false;
                    opencancom.Text = opencom.Text = CMD.CANMode? "关闭CAN": "关闭串口";
                    //statusstring = "已连接";
                    //clawclear();

                    commodelabel3.Text = CMD.CANMode ? "CAN模式" : "RS485模式";
                    if (CMD.CANMode)
                        if (SelectCAN.CAN_COM != null)
                            if (SelectCAN.CAN_SetBps != null) SelectCAN.CAN_SetBps(canbps[canbpsselect.SelectedIndex]);
                    if (bootloaderonly)
                    {
                        updatefw_Click(null, null);
                    }
                    CMD_DR_Click(null, null);
                }
            }
        }

        int[] getsettinginfo()
        {
            int[] info = new int[8];
            try
            {
                info[0] = int.Parse(targetpostextBox7.Text);
                info[1] = maxma_track.Value;
                info[2] = speed_trackBar2.Value;
                info[3] = int.Parse(clawtimetextBox2.Text);
                info[4] = autohomecheckBox1.Checked ? 1 : 0;
                //info[5] = homeinvcheckBox2.Checked ? 1 : 0;
                //info[6] = int.Parse(homeoffsettextBox3.Text);
                //info[7] = backma_trackBar1.Value;
                return info;
            }
            catch (Exception e){
                 errorinfo.Text= e.ToString();
            }
            return null;
        }

        void setsettinginfo(int[] info,int offset=0)
        {
            targetpostextBox7.Text = "" + info[0+offset];
            if (info[1 + offset] > maxma_track.Maximum) info[1 + offset] = maxma_track.Maximum;
            if (info[1 + offset] < maxma_track.Minimum) info[1 + offset] = maxma_track.Minimum;
            maxma_track.Value= maxma_track.Minimum;
            maxma_track.Value = info[1 + offset];
            speed_trackBar2.Value = speed_trackBar2.Minimum;
            speed_trackBar2.Value = info[2 + offset];
            clawtimetextBox2.Text = ""+info[3 + offset];
            autohomecheckBox1.Checked = info[4 + offset] != 0 ? true : false;
            //homeinvcheckBox2.Checked= info[5 + offset] != 0 ? true : false;
            //homeoffsettextBox3.Text = "" + info[6 + offset];
            //if (info[7 + offset] > backma_trackBar1.Maximum)info[7 + offset] = backma_trackBar1.Maximum;
            //if (info[7 + offset] < backma_trackBar1.Minimum) info[7 + offset] = backma_trackBar1.Minimum;
            //backma_trackBar1.Value = info[7 + offset];
            //blockset = false;
        }

        int[] getdetectinfo()
        {
            int[] info = new int[8];
            try
            {
                info[0] = int.Parse(detectmaxpostextBox8.Text);
                info[1] = motorlstrackBar3.Value*800;
                info[2] = tryParse(motorlsacctextBox2.Text,motorlsacctrackBar2.Value*8000);
                info[3] = int.Parse(detecttimetextBox7.Text);
                info[4] = detectmatrackBar1.Value;
                //info[4] = autohomecheckBox1.Checked ? 1 : 0;
                //info[5] = homeinvcheckBox2.Checked ? 1 : 0;
                //info[6] = int.Parse(homeoffsettextBox3.Text);
                //info[7] = backma_trackBar1.Value;
                return info;
            }
            catch (Exception e)
            {
                errorinfo.Text = e.ToString();
            }
            return null;
        }

        void setdetectinfo(int[] info, int offset = 2)
        {
            detectmaxpostextBox8.Text = "" + info[0 + offset];

            int maxhstrack = info[1 + offset] / 800;
            if (motorlstrackBar3.Maximum < maxhstrack)
                motorlstrackBar3.Maximum = maxhstrack;
            motorlstrackBar3.Value = info[1 + offset] / 800;


            int maxlsacc = info[2 + offset]/8000;
            if (motorlsacctrackBar2.Maximum < maxlsacc)
                motorlsacctrackBar2.Maximum = maxlsacc;
            motorlsacctrackBar2.Value = info[2 + offset] / 8000;
            motorlsacctextBox2.Text = "" + info[2 + offset];

            detecttimetextBox7.Text = "" + info[3 + offset];

            maxhstrack = info[4 + offset];
            if (detectmatrackBar1.Maximum < maxhstrack)
                detectmatrackBar1.Maximum = maxhstrack;
            detectmatrackBar1.Value = info[4 + offset];
        }

        int[] getmotorinfo()
        {
            int[] info = new int[9];
            try
            {
                info[0] = int.Parse(motormaxspeedtextBox15.Text);
                info[1] = int.Parse(motormaxaccspeedtextBox16.Text);
                info[2] = int.Parse(motormaxmatextBox17.Text);
                info[3] = motortbcheckBox1.Checked ? 1 : 0;
                info[4] = progselectcomboBox1.SelectedIndex;
                info[5] = motormodeselectcomboBox1.SelectedIndex == 0 ? 2 : 1;
                info[6] = int.Parse(motoregeartextBox2.Text);
                info[7] = int.Parse(motorferrortextBox4.Text);
                info[8] = motormulcheckBox2.Checked ? 1 : 0; ;
                return info;
            }
            catch (Exception e)
            {
                errorinfo.Text = e.ToString();
            }
            return null;
        }

        void setmotorinfo(int[] info,int offset=2)
        {
            try
            {
                int maxhstrack = info[0 + offset] / 800;
                if (motorhstrackBar1.Maximum < maxhstrack)
                    motorhstrackBar1.Maximum = maxhstrack;
                motorhstrackBar1.Value = info[0 + offset] / 800;

                int maxhsacctrack = info[1 + offset] / 8000;
                if (motormaxaccspeed2trackBar1.Maximum < maxhstrack)
                    motormaxaccspeed2trackBar1.Maximum = maxhsacctrack;
                motormaxaccspeed2trackBar1.Value = info[1 + offset] / 8000;
              

                motormaxaccspeed2textBox1.Text= motormaxaccspeedtextBox16.Text = "" + info[1 + offset];
                motormaxspeedtextBox15.Text = "" + info[0 + offset];
                motormaxmatextBox17.Text = "" + info[2 + offset];
                motortbcheckBox1.Checked = info[3 + offset] != 0 ? true : false;
                progselectcomboBox1.SelectedIndex = info[4 + offset];
                motormodeselectcomboBox1.SelectedIndex = (info[5 + offset] == 2) ? 0 : 1;
                motoregeartextBox2.Text = "" + info[6 + offset];
                motorferrortextBox4.Text = "" + info[7 + offset];
                motormulcheckBox2.Checked = info[8 + offset] != 0 ? true : false;
            }
            catch { }
        }

        int[] gethomeinfo()
        {
            int[] info = new int[9];
            try
            {
                info[0] = homeid[homemodeselectcomboBox3.SelectedIndex];
                info[1] = int.Parse(homespeedtextBox9.Text);
                info[2] = int.Parse(homeaccspeedtextBox11.Text);
                info[3] = int.Parse(homeoffsettextBox10.Text);
                info[4] = int.Parse(homematextBox12.Text);
                info[5] = homeioinvcheckBox3.Checked ? 1 : 0;
                info[6] = int.Parse(hometimetextBox13.Text);
                info[7] = int.Parse(homemaxpostextBox14.Text);
                return info;
            }
            catch (Exception e)
            {
                errorinfo.Text = e.ToString();
            }
            return null;
        }

        void sethomeinfo(int[] info,int offset=2)
        {
            homemodeselectcomboBox3.SelectedIndex = homeid.IndexOf(info[0 + offset]);
            homespeedtextBox9.Text = "" + info[1 + offset];
            homeaccspeedtextBox11.Text = "" + info[2 + offset];
            homeoffsettextBox10.Text = "" + info[3 + offset];
            homematextBox12.Text = "" + info[4 + offset];
            homeioinvcheckBox3.Checked = info[5 + offset] != 0 ? true : false;
            hometimetextBox13.Text = "" + info[6 + offset];
            homemaxpostextBox14.Text = "" + info[7 + offset];
        }

        

        int[] getpidinfo()
        {
            int[] info = new int[3];
            try
            {
                info[0] = int.Parse(pid_kp_textBox1.Text);
                info[1] = int.Parse(pid_ki_textBox2.Text);
                info[2] = int.Parse(pid_kd_textBox3.Text);
                return info;
            }
            catch (Exception e)
            {
                errorinfo.Text = e.ToString();
            }
            return null;
        }

        void setpidinfo(int[] info, int offset = 2)
        {
            pid_kp_trackBar1.Value = info[offset + 0];
            pid_ki_trackBar2.Value = info[offset + 1];
            pid_kd_trackBar3.Value = info[offset + 2];
        }

        int[] getwinfo()
        {
            int[] info = new int[5];
            try
            {
                info[0] = maxma2_track.Value;
                info[1] = speed2_trackBar2.Value;
                info[2] = 0;
                info[3] = 0;
                info[4] = 0;
                return info;
            }
            catch (Exception e)
            {
                errorinfo.Text = e.ToString();
            }
            return null;
        }

        void setwinfo(int[] info, int offset = 2)
        {
            maxma2_track.Value = maxma2_track.Minimum;
            maxma2_track.Value = info[offset + 0];
            speed2_trackBar2.Value = speed2_trackBar2.Minimum;
            speed2_trackBar2.Value = info[offset + 1];
        }

        private void getcombutton13_Click(object sender, EventArgs e)
        {
            comselect.Items.Clear();
            getPortDeviceName(comselect);
            opencom.Enabled = comselect.Items.Count!=0;
            if (comselect.Items.Count!=0)
                comselect.SelectedIndex = 0;
        }
        
        private void CMD_DR_Click(object sender, EventArgs e)
        {
            iwiew++;
            cmdblocktimes = cmdblockCount;
            clawclear(0);
            SendUartData(CMD['$']);
        }

        private void enabeclawbutton4_Click(object sender, EventArgs e)
        {
            SendUartData(CMD['E', SelectClawID,1]);
        }

        private void disableclawbutton5_Click(object sender, EventArgs e)
        {
            SendUartData(CMD['E', SelectClawID, 2]);
        }

        private void homebutton6_Click(object sender, EventArgs e)
        {
            homebutton6.Text = "回零";
            SendUartData(CMD['G', SelectClawID, 2]);
            homestatscheck = true;
        }


        void writeCMD()
        {
            int[] info;
            if (cmdwrite.Count != 0)
            {
                switch (cmdwrite[0])
                {
                    case 'n':
                        info = getsettinginfo();
                        if (info != null)
                            SendUartData(CMD['n', SelectClawID, info]);
                        break;
                    case 'f':
                        info = getdetectinfo();
                        if (info != null)
                            SendUartData(CMD['f', SelectClawID, info]);
                        break;
                    case 'r':
                        info = getmotorinfo();
                        if (info != null)
                            SendUartData(CMD['r', SelectClawID, info]);
                        break;
                    case 'b':
                        info = gethomeinfo();
                        if (info != null)
                            SendUartData(CMD['b', SelectClawID, info]);
                        break;
                    case 'p':
                        info = getpidinfo();
                        if (info != null)
                            SendUartData(CMD['p', SelectClawID, info]);
                        break;
                    case 'w':
                        info = getwinfo();
                        if (info != null)
                            SendUartData(CMD['w', SelectClawID, info]);
                        break;
                }
                cmdwrite.RemoveAt(0);
            }
        }
        private void updatedatabutton2_Click(object sender, EventArgs e)
        {
            switch (tabControl1.SelectedIndex)
            {
                case 0:
                    cmdwrite.Add('b');
                    cmdwrite.Add('n');
                    cmdwrite.Add('w');
                    break;
                case 1:
                    cmdwrite.Add('f');
                    cmdwrite.Add('r');
                    break;
                case 2:
                    cmdwrite.Add('r');
                    cmdwrite.Add('b');
                    break;
                case 3:
                    cmdwrite.Add('p');
                    break;
            }
            writeCMD();
        }

        private void readdatabutton7_Click(object sender, EventArgs e)
        {
            switch(tabControl1.SelectedIndex)
            {
                case 0:
                    cmdlist.Add('B');
                    cmdlist.Add('N');
                    cmdlist.Add('W');
                    break;
                case 1:
                    cmdlist.Add('F');
                    cmdlist.Add('R');
                    break;
                case 2:
                    cmdlist.Add('B');
                    cmdlist.Add('R');
                    break;
                case 3:
                    cmdlist.Add('P');
                    break;
            }
            //int[] data = CMD[">01E38F21"];
        }

        private void CMD_enable_Click(object sender, EventArgs e)
        {
            SendUartData(CMD['a', SelectClawID,1]);
        }

        private void disablemotor_b_Click(object sender, EventArgs e)
        {
            SendUartData(CMD['a', SelectClawID, 0]);
        }

        private void motorcal_b_Click(object sender, EventArgs e)
        {
            if (warrinfocheckBox3.Checked || MessageBox.Show("点击确定开始校准电机", "警告", MessageBoxButtons.OKCancel,MessageBoxIcon.Question) == DialogResult.OK)
            {
                ZcmdFlag = true;
                SendUartData(CMD['Z', SelectClawID]);
            }
        }

        private void maxma_track_ValueChanged(object sender, EventArgs e)
        {
            maxma_text.Text = "" + maxma_track.Value;
            realtimema.ChartAreas[0].AxisY.Maximum = maxma_track.Value+5;
            //maxma_text.Text = "" + maxma_track.Value*100/255;
            needUpdate = !blockset;
        }

        private void backma_trackBar1_ValueChanged(object sender, EventArgs e)
        {
            homematextBox12.Text = backma_textBox1.Text = "" + backma_trackBar1.Value;
            
            needUpdate = !blockset;
        }

        private void speed_trackBar2_ValueChanged(object sender, EventArgs e)
        {
            speed_textBox4.Text = "" + speed_trackBar2.Value;
            needUpdate = !blockset;
        }

        void setTrack(TrackBar t, int value)
        {
            if (t.Maximum < value)
                value = t.Maximum;
            if (t.Minimum > value)
                value = t.Minimum;
            t.Value = value;
        }

        void LinkTextTrack(TrackBar t, TextBox b)
        {
            b.TextChanged += (s, e) => {
                setTrack(t, tryParse(b.Text, t.Value));
            };
            b.LostFocus += (s, e) => {
                try
                {
                    t.Value = int.Parse(b.Text);
                }
                catch { b.Text = "" + t.Value; }
            };
            t.Scroll += (s, e) => {
                b.Text = "" + t.Value;
            };
        }

        void linktracktext(TrackBar tb, TextBox t, double rate = 1)
        {
            trsValue.Add(tb, rate);
            EventHandler act= (object s, EventArgs e) => {
                if (t.Tag != null)
                {
                    t.Tag = null;
                    return;
                }
                t.Text = "" + (int)(tb.Value*trsValue[(Control)s]);
            };
            tb.ValueChanged += act;
            t.KeyDown += (object sx, KeyEventArgs ex) => {
                ((Control)sx).Tag = true;
                textsettrack(tb, t, ex, (object s, EventArgs e) => {
                    if (t.Tag != null)
                    {
                        t.Tag = null;
                        return;
                    }
                    t.Text = "" + (int)(tb.Value * trsValue[(Control)s]);
                });
            };
            t.LostFocus += (s, e) => {
                try
                {
                    tb.Value = (int)(int.Parse(t.Text) / trsValue[tb]);
                }
                catch { t.Text = "" + (int)(tb.Value * trsValue[tb]); }
            };
        }

        private void poscontroltrackBar3_ValueChanged(object sender, EventArgs e)
        {
            poscontorltextBox6.Text = "" + poscontroltrackBar3.Value;
        }

        void textsettrack(TrackBar t, TextBox b, KeyEventArgs e,Action<object, EventArgs> act)
        {
            if (e != null)
                if (e.KeyCode != Keys.Enter) return;
            var sender = t;
            try
            {
                int value = int.Parse(b.Text);

                if (trsValue.ContainsKey((Control)sender))
                    value = (int)(value /  trsValue[(Control)sender]);
                if (value > t.Maximum) value = t.Maximum;
                if (value < t.Minimum) value = t.Minimum;

                //

                t.Value = value;
                needUpdate = !blockset;
            }
            catch { act(t, null); }
        }

        private void maxma_text_KeyDown(object sender, KeyEventArgs e)
        {
            textsettrack(maxma_track, maxma_text, e, maxma_track_ValueChanged);

            //if (e != null)
            //    if (e.KeyCode != Keys.Enter) return;
            //TrackBar t = maxma_track;
            //TextBox b = maxma_text;
            //try
            //{
            //    int value = int.Parse(b.Text);
            //    if (value > t.Maximum) value = t.Maximum;
            //    if (value < t.Minimum) value = t.Minimum;

            //    //

            //    t.Value = value;
            //    needUpdate = !blockset;
            //}
            //catch { maxma_track_ValueChanged(null, null); }

        }

        private void backma_textBox1_KeyDown(object sender, KeyEventArgs e)
        {
            textsettrack(backma_trackBar1, backma_textBox1, e, backma_trackBar1_ValueChanged);
            //if (e != null)
            //    if (e.KeyCode != Keys.Enter) return;
            //TrackBar t = backma_trackBar1;
            //TextBox b = backma_textBox1;
            //try
            //{
            //    int value = int.Parse(b.Text);
            //    if (value > t.Maximum) value = t.Maximum;
            //    if (value < t.Minimum) value = t.Minimum;

            //    //
            //    t.Value = value;
            //    needUpdate = !blockset;
            //}
            //catch { backma_trackBar1_ValueChanged(null, null); }
        }

        private void speed_textBox4_KeyDown(object sender, KeyEventArgs e)
        {
            textsettrack(speed_trackBar2, speed_textBox4, e, speed_trackBar2_ValueChanged);
            //if (e != null)
            //    if (e.KeyCode != Keys.Enter) return;
            //TrackBar t = speed_trackBar2;
            //TextBox b = speed_textBox4;
            //try
            //{
            //    int value = int.Parse(b.Text);
            //    if (value > t.Maximum) value = t.Maximum;
            //    if (value < t.Minimum) value = t.Minimum;

            //    //

            //    t.Value = value;
            //    needUpdate = !blockset;
            //}
            //catch { speed_trackBar2_ValueChanged(null, null); }
        }

        private void poscontorltextBox6_KeyDown(object sender, KeyEventArgs e)
        {

        }

        private void infobutton1_Click(object sender, EventArgs e)
        {
            SendUartData(CMD['I', SelectClawID]);
            Iwiew++;
        }

        private void clawselectcomboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (skipselect)
            {
                skipselect = false;
                return;
            }
            clawnumtextBox5.Text = "" + clawnum[clawselectcomboBox1.SelectedIndex];
            SelectClawID = clawnum[clawselectcomboBox1.SelectedIndex];
            setnumberbutton9.Enabled = (SelectClawID != 0);
            if (infoautogetcheckBox1.Checked)
                if (SelectClawID != 0)
                {
                    //选择设备时清空buff避免其他设置写入新设备
                    clearrwlist();

                    blockset = true;
                    cmdlist.Add('A');
                    cmdlist.Add('R');
                    cmdlist.Add('N');
                    cmdlist.Add('W');
                    cmdlist.Add('B');
                    cmdlist.Add('F');
                    cmdlist.Add('P');
                }
        }

        private void clearrwlist()
        {
            cmdlist.Clear();
            cmdreadtimeout.Clear();
            cmdwrite.Clear();
            cmdwritetimeout.Clear();
        }

        private void setnumberbutton9_Click(object sender, EventArgs e)
        {
            int newid = -1;
            try
            {
                newid = int.Parse(clawnumtextBox5.Text);
                if(newid<0||newid>255)
                    throw new Exception();
            }
            catch {
                MessageBox.Show("站号输入错误,范围必须在0-255内");
                return;
            }

            if (clawselectcomboBox1.SelectedIndex == 0)
            {
                if (warrinfocheckBox3.Checked || MessageBox.Show( "该操作将广播到所有设备", "警告", MessageBoxButtons.OKCancel)==DialogResult.OK)
                {
                   SendUartData(CMD['i', SelectClawID,newid]);
                }
            }
            else
            {
                SendUartData(CMD['i', SelectClawID, newid]);
            }
        }

        private void clawtimetextBox2_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
               
            }
        }

        private void homeoffsettextBox3_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {

            }
        }

        private void autohomecheckBox1_CheckedChanged(object sender, EventArgs e)
        {
            needUpdate = !blockset;
        }

        private void rdstats_b_Click(object sender, EventArgs e)
        {
            SendUartData(CMD['d', SelectClawID]);
        }

        void setcombps(int bps) {
            if (COM.BaudRate == bps) return;
            if (COM.IsOpen)
            {
                COM.Close();
                COM.BaudRate = bps;
                COM.Open();
            }
        }
        private void updatefw_Click(object sender, EventArgs e)
        {
            if (CMD.CANMode)
            {
                MessageBox.Show("CAN模式不支持更新固件");
                return;
            }
            
            if (dl == null)
            {
                dl = new YmodemGUI(SendUartBytes, dlbuffer);
                dl.uartcmdsender = (byte[] b) => {
                    if (CRC16ENcheckBox1.Checked)
                    {
                        var str = Encoding.Default.GetString(b).Replace("\r\n", "");
                        var crc = CMD.AppendCRCHex(str);
                        var crcdata = new byte[] { crc[0], crc[1], (byte)'\r', (byte)'\n' };
                        SendUartBytes(Encoding.Default.GetBytes(str));
                        SendUartBytes(crcdata);
                    }
                    else
                    {
                        SendUartBytes(b);
                    }
                };
                dl.setbps = setcombps;
            }
            if (!(clawselectcomboBox1.SelectedItem as string).ToLower().Contains("cstep"))
            {
                if (MessageBox.Show("无法获取设备版本\n是否手动选择?(选错版本将导致无法恢复)", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                {
                    if (dl.fwurl.Count == 0)
                    {
                        dl.fwurl.Add("Cstep v", "https://gitee.com/Cccxs/cstep-open/raw/master/FW/"); dl.fwconnbps.Add("Cstep v", 115200);
                        dl.fwurl.Add("Cstep [A]", "https://gitee.com/Cccxs/cstep-open/raw/master/FW/"); dl.fwconnbps.Add("Cstep [A]", 115200);
                        dl.fwurl.Add("Cstep [B]", "https://gitee.com/Cccxs/cstep-open/raw/master/[B]FW/"); dl.fwconnbps.Add("Cstep [B]", 115200);
                        dl.fwurl.Add("Cstep [C]", "https://gitee.com/Cccxs/cstep-open/raw/master/[C]FW/"); dl.fwconnbps.Add("Cstep [C]", 115200);
                        dl.fwurl.Add("Cstep [D]", "https://gitee.com/Cccxs/cstep-open/raw/master/[D]FW/"); dl.fwconnbps.Add("Cstep [D]", 115200);
                        dl.fwurl.Add("Cstep [E]", "https://gitee.com/Cccxs/cstep-open/raw/master/[E]FW/"); dl.fwconnbps.Add("Cstep [E]", 115200);
                    }
                    dl.freeselect = true;
                }
                else
                    return;
            }
            dlMode = true;
            int lastid = SelectClawID;
            clawselectcomboBox1.SelectedIndex = 0;

            var var = clawselectcomboBox1.Items[clawnum.IndexOf(lastid)].ToString();
            foreach(var k in fwurl.Keys)
            {
                if (var.Contains(k))
                {
                    dl.urldata = fwurl[k];
                }
            }
            dl.StartPosition = FormStartPosition.CenterParent;
            dl.defbps = COM.BaudRate;
            dl.rate = 6300;
            dl.beforCMD = string.Format("[iap=1,{0},{{0}}]\r\n", lastid);
            dl.ShowDialog();
            dlMode = false;
            setcombps(dl.defbps);


            if (bootloaderonly)
                if (COM.IsOpen)
                    opencom_Click(null, null);
        }

        private void txinfo_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                txlastdataButton_Click(null, null);
            }
        }

        private void poscontroltrackBar3_MouseDown(object sender, MouseEventArgs e)
        {
            PosUserControl = true;
        }

        private void poscontroltrackBar3_MouseUp(object sender, MouseEventArgs e)
        {
            PosUserControl = false;
        }

        private void poscontroltrackBar3_MouseLeave(object sender, EventArgs e)
        {
            PosUserControl = false;
        }

        private void poscontroltrackBar3_Scroll(object sender, EventArgs e)
        {
            if (enableposcontrol.Checked)
                SendUartData(CMD['D', SelectClawID, poscontroltrackBar3.Value]);
        }

        private void savedatabutton8_Click(object sender, EventArgs e)
        {
            SendUartData(CMD['U', SelectClawID]);
        }

        private void enableposcontrol_CheckedChanged(object sender, EventArgs e)
        {
            if (enableposcontrol.Checked)
            {
                //if (!warrinfocheckBox3.Checked)
                //    if (MessageBox.Show("该功能仅限于确定夹抓位置时使用", "警告", MessageBoxButtons.OKCancel) != DialogResult.OK)
                //        enableposcontrol.Checked = false;
            }
            abspossetbutton2.Enabled=abspossetbutton1.Enabled= poscontorltextBox6.Enabled = poscontroltrackBar3.Enabled = enableposcontrol.Checked;

        }

        private void txlastdataButton_Click(object sender, EventArgs e)
        {
            if (txinfo.Text.Length == 0) return;
            if (CMD.CANMode)
            {
                var data = new int[12];
                var dat = new byte[13];
                if (10 != CMD.formatRead(txinfo.Text, "CAN[%8x][%2x][ %2x %2x %2x %2x %2x %2x %2x %2x ]", data)) return;
                dat[11] = (byte)((data[0] >> 24) & 0xff);
                dat[10] = (byte)((data[0] >> 16) & 0xff);
                dat[9] = (byte)((data[0] >> 8) & 0xff);
                dat[8] = (byte)((data[0] >> 0) & 0xff);
                can_framerset = data[1];
                dat[12] = (byte)can_framerset;
                for(int i = 0; i < 8; i++)
                {
                    dat[i] = (byte)data[i+2];
                }
                SendUartData(dat);
            }
            else
            {
                if (CRC16ENcheckBox1.Checked)
                {
                    if (txinfo.Text.Contains("\r\n"))
                    {
                        var crc = CMD.AppendCRCHex(txinfo.Text.Replace("\r\n", ""));
                        var crcdata = new byte[] { crc[0], crc[1], (byte)'\r', (byte)'\n' };
                        SendUartData(txinfo.Text.Replace("\r\n", ""));
                        SendUartData(crcdata);
                    }
                    else if (txinfo.Text[0] == '>')
                        SendUartData(CMD.AppendCRC(txinfo.Text) + "\r\n", false);
                    else
                    {
                        var crc = CMD.AppendCRCHex(txinfo.Text);
                        var crcdata = new byte[] { crc[0], crc[1], (byte)'\r', (byte)'\n' };
                        SendUartData(txinfo.Text);
                        SendUartData(crcdata);
                    }
                }
                else
                {
                    if (txinfo.Text.Contains("\r\n"))
                        SendUartData(txinfo.Text);
                    else if (txinfo.Text[0] == '>')
                        SendUartData(CMD.AppendCRC(txinfo.Text) + "\r\n", false);
                    else
                        SendUartData(txinfo.Text + "\r\n");
                }
            }

        }

        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (tabControl1.SelectedIndex == 0)
            {
                enabeclawbutton4.Visible = disableclawbutton5.Visible = true;
            }
            if (tabControl1.SelectedIndex == 1)
            {
                enabeclawbutton4.Visible = disableclawbutton5.Visible = false;
            }
            detectruninfo.Visible = lqdetectbutton2.Visible = assemblybutton1.Visible = !enabeclawbutton4.Visible;
        }

        private void lqdetectbutton2_Click(object sender, EventArgs e)
        {
            try
            {
                SendUartData(CMD['j', SelectClawID, int.Parse(detecthspostextBox6.Text), int.Parse(detectdeeptextBox5.Text)]);
            }
            catch { MessageBox.Show("参数错误"); };
        }

        private void assemblybutton1_Click(object sender, EventArgs e)
        {
            try { 
            SendUartData(CMD['m', SelectClawID, int.Parse(assemblytextBox1.Text)]);
            }
            catch { MessageBox.Show("参数错误"); }
        }

        private void TextBoxTrackBar_ValueChanged(object sender, EventArgs e)
        {
            if (trsValue.ContainsKey((Control)sender))
            {
                ((Control)((Control)sender).Tag).Text = "" + ((TrackBar)sender).Value* trsValue[(Control)sender];
            }
            else
                ((Control)((Control)sender).Tag).Text = "" + ((TrackBar)sender).Value;
        }

        private void motorhstextBox1_KeyDown(object sender, KeyEventArgs e)
        {

        }

        private void nonoise(object sender, KeyPressEventArgs e)
        {
            if(e.KeyChar==13)
            e.Handled = true;
        }

        int tryParse(string s,int defvalue)
        {
            int value = 0;
            if(int.TryParse(s, out value))
            return value;
            return defvalue;
        }

        private void motorhstrackBar1_Scroll(object sender, EventArgs e)
        {
            motormaxspeedtextBox15.Text = "" + motorhstrackBar1.Value*800;
            motormaxaccspeedtextBox16.Text = "" + tryParse(motormaxaccspeed2textBox1.Text, motormaxaccspeed2trackBar1.Value*8000);
        }

        private void motorbkbutton1_Click(object sender, EventArgs e)
        {
            SendUartData(CMD['K', SelectClawID, 0]);
        }

        private void testturnleft_Click(object sender, EventArgs e)
        {
            SendUartData(CMD['K', SelectClawID, 1]);
        }

        private void testturnright_Click(object sender, EventArgs e)
        {
            SendUartData(CMD['K', SelectClawID, 2]);
        }

        private void homesetzero_Click(object sender, EventArgs e)
        {
            var info=gethomeinfo();
            if (info != null)
            {
                info[0] = (int)HOME_MODE.HOME_ACT_POS;
                SendUartData(CMD['b', SelectClawID, info]);
            }
        }

        private void testturnleft_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                SendUartData(CMD['K', SelectClawID, 1]);
            }
        }

        private void testturnright_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                SendUartData(CMD['K', SelectClawID, 2]);
            }
        }

        private void testturnleft_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                SendUartData(CMD['K', SelectClawID, 0]);
            }
        }

        private void gettextLocation(object sender, EventArgs e)
        {
            (((Control)sender).Tag as TextBox).Text = ""+poscontroltrackBar3.Value;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Text = softname + ver;
            if (bootloaderonly) return;
            tabControl1_SelectedIndexChanged(null, null);
            if (System.IO.File.Exists(cfgpath))
                new System.Threading.Thread(() => { loadconfig(); }).Start();
            
            //var fs = new dmactool.CanProcess();
            //var data=fs.SendToCan(COM, "0000000000000000", "00000401", "1", "1",0,1,0,0);
            //CMD.CANMode = true;
            //var info = getsettinginfo();
            //var dat2 = CMD['I', 1];
            //CMD.CANMode = false;
            //CMD.canBuffer.AddRange(new byte[] { 0xAA, 0x11, 0x48, 0x01, 0x04, 0x01, 0x00, 0x0F, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x55 });
            //CMD.candecode();
            //foreach (byte b in data)
            //{
            //    datainfo.AppendText(string.Format("{0:X2} ",b));
            //}
            //foreach (byte b in dat2 as byte[])
            //{
            //    datainfo.AppendText(string.Format("{0:X2} ", b));
            //}
            //var d=CMD[">02R000493E0000F424078000012710000003200CE98"];
            //setmotorinfo(d);
        }

        private void motormodeselectcomboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (motormodeselectcomboBox1.SelectedIndex)
            {
                case 0:
                    progselectcomboBox1.SelectedIndex = 3;
                    break;
                case 1:
                    progselectcomboBox1.SelectedIndex = 0;
                    break;
            }
            //updatedatabutton2_Click(null, null);
            //if (tabControl1.SelectedIndex == 0)
            //{
            //    enabeclawbutton4.Visible = disableclawbutton5.Visible = true;
            //}
            //if (tabControl1.SelectedIndex == 1)
            //{
            //    enabeclawbutton4.Visible = disableclawbutton5.Visible = false;
            //}
            //lqdetectbutton2.Visible = assemblybutton1.Visible = !enabeclawbutton4.Visible;
        }

        private void saveinfocheck_CheckedChanged(object sender, EventArgs e)
        {
            saveconfig();
        }

        private void configpathbutton1_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("explorer.exe", "/select,\""+cfgpath+"\"");
        }

        private void exttoolsbutton12_Click(object sender, EventArgs e)
        {
            //1093,832
            g4.Visible = !g4.Visible;
            if (g4.Visible)
                Size = new Size(1093, Size.Height);
            else
                Size = new Size(832, Size.Height);
        }

        private void abspossetbutton1_Click(object sender, EventArgs e)
        {
            try
            {
                SendUartData(CMD['D', SelectClawID, int.Parse((abspossetbutton1 == sender ? usersetpostextBox1 : usersetpostextBox2).Text)]);
            }
            catch { }
        }

        private void uabsposetbutton2_Click(object sender, EventArgs e)
        {
            try
            {
                SendUartData(CMD['h', SelectClawID, int.Parse((uabsposetbutton2 == sender ? usersetpostextBox1 : usersetpostextBox2).Text), 0xff]);
            }
            catch { }
        }

        private void motorlstrackBar3_Scroll(object sender, EventArgs e)
        {

        }

        List<TabPage> savepage = new List<TabPage>();
        private List<List<string>> configcache = new List<List<string>>();
        private StringBuilder datainfocache=new StringBuilder();
        private byte[] datainfobigchar=new byte[2];
        private int posmax;
        private int posmin;
        private int chartupdatesize;
        private int chartupdatevalue;
        private int errorcount;
        const int MAXUSERUARTCMD = 99;

        private void idinfocheck_CheckedChanged(object sender, EventArgs e)
        {
            
            if (idinfocheck.Checked)
            {
                idinfocheck.Location = new Point(277, 68);
                for(int i = 1; i < savepage.Count; i++)
                    tabControl1.TabPages.Add(savepage[i]);
                
            }
            else
            {
                idinfocheck.Location = new Point(94, 68);
                for (int i = 1; i < savepage.Count; i++)
                    tabControl1.TabPages.RemoveAt(1);
            }
        }

        private void homeoffsettextBox10_TextChanged(object sender, EventArgs e)
        {
            homeoffsettextBox3.Text = homeoffsettextBox10.Text;
        }

        private void homeoffsettextBox3_TextChanged(object sender, EventArgs e)
        {
            homeoffsettextBox10.Text = homeoffsettextBox3.Text;
        }

        private void homematextBox12_TextChanged(object sender, EventArgs e)
        {
            backma_textBox1.Text = homematextBox12.Text;
            backma_textBox1_KeyDown(null, null);
        }

        private void reset_b_Click(object sender, EventArgs e)
        {
            SendUartData(CMD['Q', SelectClawID]);
        }

        private void motorhstextBox1_KeyDown_1(object sender, KeyEventArgs e)
        {
            textsettrack(motorhstrackBar1, motorhstextBox1, e, TextBoxTrackBar_ValueChanged);
        }

        private void motorlstextBox3_KeyDown(object sender, KeyEventArgs e)
        {
            
            textsettrack(motorlstrackBar3, motorlstextBox3, e, TextBoxTrackBar_ValueChanged);
        }

        private void detectmatextBox1_KeyDown(object sender, KeyEventArgs e)
        {
            textsettrack(detectmatrackBar1, detectmatextBox1, e, TextBoxTrackBar_ValueChanged);
        }

        private void updatelinkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            string urldata = "https://gitee.com/KeyMove/wontec_claw/raw/master/wontec_claw/bin/Release/";
            try
            {
                var info = YmodemGUI.HttpGetPage(urldata + updatename).Replace("\r", "").Split('\n');
                var reqdl = new List<string>();
                foreach (var fn in info)
                {
                    if(fn.Length!=0)
                    if(!File.Exists(Environment.CurrentDirectory + "/" + fn + ".exe"))
                    {
                        if (fn != Text)
                            reqdl.Add(fn);
                    }
                }
                if (reqdl.Count==0)
                {
                    if (info[0] != Text)
                    {
                        if (MessageBox.Show($"新版本{info[0]}文件已存在,切换到新版本?", "提示", MessageBoxButtons.YesNo,MessageBoxIcon.Question) == DialogResult.Yes)
                        {
                            Process.Start(Environment.CurrentDirectory + "/" + info[0] + ".exe");
                            Application.Exit();
                        }
                    }
                    else if (sender != null)
                    {
                        MessageBox.Show("已是最新版本");
                        return;
                    }
                    else
                        return;
                }
                if (MessageBox.Show($"检测到新版本{reqdl[0]}\r\n是否更新?", "更新检测", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) != DialogResult.OK) return;
                string dlfile = "";
                foreach (var dl in reqdl)
                {
                    var data = YmodemGUI.HttpGetPageData(urldata + dl + ".exe");
                    if (data != null)
                    {
                        var fs = File.Create(Environment.CurrentDirectory + "/" + dl + ".exe");
                        fs.Write(data, 0, data.Length);
                        fs.Flush();
                        fs.Close();
                        dlfile += "[" + dl + "]";
                    }
                    else
                    {
                        MessageBox.Show("下载文件"+dl+"失败");
                        return;
                    }
                }
                if (MessageBox.Show("下载" + dlfile + "成功,切换到新版本?", "提示", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    Process.Start(Environment.CurrentDirectory + "/" + info[0] + ".exe");
                    Application.Exit();
                }
            }
            catch (Exception ex) { if(sender!=null)MessageBox.Show("下载文件失败"); }
        }

        private void homeioinvcheckBox3_CheckedChanged(object sender, EventArgs e)
        {
            homeioinvradioButton1.Checked = !homeioinvcheckBox3.Checked;
        }

        private void homeioinvradioButton1_CheckedChanged(object sender, EventArgs e)
        {
            homeioinvcheckBox3.Checked = !homeioinvradioButton1.Checked;
        }

        private void pid_kp_trackBar1_ValueChanged(object sender, EventArgs e)
        {
            pid_kp_textBox1.Text = "" + pid_kp_trackBar1.Value;
        }

        private void pid_ki_trackBar2_ValueChanged(object sender, EventArgs e)
        {
            pid_ki_textBox2.Text = "" + pid_ki_trackBar2.Value;
        }

        private void pid_kd_trackBar3_ValueChanged(object sender, EventArgs e)
        {
            pid_kd_textBox3.Text = "" + pid_kd_trackBar3.Value;
        }

        private void saveconfigToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var list = new List<string>();
            int[] info;
            info = getsettinginfo();
            if (info != null)
                list.Add(CMD['n', SelectClawID, info] as string);
            info = getdetectinfo();
            if (info != null)
                list.Add(CMD['f', SelectClawID, info] as string);
            info = getmotorinfo();
            if (info != null)
                list.Add(CMD['r', SelectClawID, info] as string);
            info = gethomeinfo();
            if (info != null)
                list.Add(CMD['b', SelectClawID, info] as string);
            info = getpidinfo();
            if (info != null)
                list.Add(CMD['p', SelectClawID, info] as string);
            configcache.Add(list);
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://gitee.com/Cccxs/cstep-open/wikis/pages");
        }

        private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("https://gitee.com/Cccxs/cstep-open/issues");
        }

        private void linkLabel3_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            dlMode = true;
            
            if (dl2 == null)
            {
                dl2 = new sersonview(SendUartBytes, dlbuffer);
            }
            dl2.ShowDialog();
            dlMode = false;

        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            if(!panel2.AutoScroll)
                panel2.AutoScroll = true;
        }

        private void othersetting_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            extinfopanel.Visible = !extinfopanel.Visible;
            if (extinfopanel.Visible)
                extinfopanel.Focus();
        }

        private void extinfopanel_Leave(object sender, EventArgs e)
        {
            extinfopanel.Visible = false;
        }

        //private void getcombutton1_Click(object sender, EventArgs e)
        //{
        //    cancomselect.Items.Clear();
        //    getPortDeviceName(cancomselect);
        //    opencancom.Enabled = cancomselect.Items.Count != 0;
        //    if (cancomselect.Items.Count != 0)
        //        cancomselect.SelectedIndex = 0;
        //}
    }
}
